package ink.xiaobaibai.controller.monthly;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import ink.xiaobaibai.annotation.InsidePublicResources;
import ink.xiaobaibai.autoConfig.roleResources.ResourcesRoleMapping;
import ink.xiaobaibai.bo.SelectMonDeviceBo;
import ink.xiaobaibai.common.AddTimeTaskBo;
import ink.xiaobaibai.common.MyRole;
import ink.xiaobaibai.common.PageInfo;
import ink.xiaobaibai.common.TimedTask;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.MonthlyDeviceStatus;
import ink.xiaobaibai.multipleClick.ForbidMultipleClick;
import ink.xiaobaibai.response.ResponseCode;
import ink.xiaobaibai.response.ResponseFormat;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.units.MySecurity;
import ink.xiaobaibai.valited.UpdateGroup;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description: 机器接口
 * @author: 小白白
 * @create: 2021-05-31
 **/

@RestController
@Api(tags = "月费机器接口")
@RequestMapping("/monthly/device")
@CrossOrigin
@InsidePublicResources
public class DeviceController {

    @Autowired
    private IMonthlyfeeDeviceService monthlyfeeDeviceService;

    @Autowired
    private IMonthlyOxygenDeviceService oxygenDeviceService;

    @Autowired
    private IAdminUserService adminUserService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IMonthlyUserDeviceService userDeviceService;

    @Autowired
    private IMonthlyTimedTaskService timedTaskService;

    @Resource
    private RestTemplate restTemplate;

    @Value("${clientPort}")
    public int clientPort;

    /**
     * 查看包月氧气机器集合
     */
    @PostMapping("/oxygen-list")
    @ApiOperation("查看包月氧气机器集合")
    public ResponseFormat getOxygenList(@RequestBody SelectMonDeviceBo selectMonDeviceBo) {
        /**
         * 机器查询条件校验
         */
        ResponseFormat responseFormat = this.validDeviceSelectBo(selectMonDeviceBo);
        if (responseFormat.getCode() == ResponseCode.ERROR.getCode()) {
            return responseFormat;
        }
        return ResponseFormat.success(this.oxygenDeviceService.getOxygenDeviceList(selectMonDeviceBo));
    }

    /**
     * 查看机器集合
     */
    @PostMapping("/ozone-list")
    @ApiOperation("查看包月臭氧机器集合")
    public ResponseFormat getDeviceList(@RequestBody SelectMonDeviceBo selectMonDeviceBo) {
        ResponseFormat responseFormat = this.validDeviceSelectBo(selectMonDeviceBo);
        if (responseFormat.getCode() == ResponseCode.ERROR.getCode()) {
            return responseFormat;
        }
        PageInfo<MonthlyfeeDevice> pageInfo = this.monthlyfeeDeviceService.getDeviceList(selectMonDeviceBo);
        // 当前机器里有没有被托管的机器
        Map<Integer, MonthlyfeeDevice> map = new HashMap<>();
        for (MonthlyfeeDevice device : pageInfo.getData()) {
            device.setTrusteeship(false);
            map.put(device.getId(), device);
        }
        List<Integer> ids = pageInfo.getData().stream().map(MonthlyfeeDevice::getId).collect(Collectors.toList());
        if (ids.size() != 0) {
            QueryWrapper<MonthlyUserDevice> q1 = new QueryWrapper<>();
            q1.select("device_id", "trusteeship");
            q1.in("device_id", ids);
            List<MonthlyUserDevice> monthlyUserDevices = this.userDeviceService.list(q1);
            for (MonthlyUserDevice monthlyUserDevice : monthlyUserDevices) {
                map.get(monthlyUserDevice.getDeviceId()).setTrusteeship(monthlyUserDevice.getTrusteeship());
                map.get(monthlyUserDevice.getDeviceId()).setLending(true);
            }
        }

        return ResponseFormat.success(pageInfo);
    }

    /**
     * 添加包月氧气设备
     */
    @PostMapping("/oxygen-add")
    @ApiOperation("添加氧气包月设备")
    @ForbidMultipleClick(key = "#monthlyOxygenDevice.deviceCode")
    @ResourcesRoleMapping(resourceName = "添加氧气包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat addOxygenDevice(@RequestBody @Validated MonthlyOxygenDevice monthlyOxygenDevice) {
        Integer userId = MySecurity.getUserId();
        String deviceCode = monthlyOxygenDevice.getDeviceCode();
        if (!this.oxygenDeviceService.codeOk(deviceCode)) {
            return ResponseFormat.fail("设备码重复");
        }
        if (monthlyOxygenDevice.getAdminUserId() == null) {
            Integer depId = this.adminUserService.getDepId(userId);
            monthlyOxygenDevice.setAdminDepId(depId);
            monthlyOxygenDevice.setAdminUserId(userId);
        } else {
            if (!this.adminUserService.existsUser(monthlyOxygenDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            monthlyOxygenDevice.setAdminDepId(this.adminUserService.getDepId(monthlyOxygenDevice.getAdminUserId()));
        }
        this.oxygenDeviceService.save(monthlyOxygenDevice);
        return ResponseFormat.success();
    }

    /**
     * 添加包月臭氧设备
     */
    @PostMapping("/ozone-add")
    @ApiOperation("添加臭氧包月设备")
    @ForbidMultipleClick(key = "#monthlyfeeDevice.deviceCode")
    @ResourcesRoleMapping(resourceName = "添加臭氧包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat addDevice(@RequestBody @Validated MonthlyfeeDevice monthlyfeeDevice) {
        Integer userId = MySecurity.getUserId();
        if (!this.monthlyfeeDeviceService.okCode(monthlyfeeDevice.getDeviceCode())) {
            return ResponseFormat.fail("识别码重复");
        }
        ResponseFormat responseFormat = this.validOxygenCode(monthlyfeeDevice.getOxygenId());
        if (responseFormat.getCode() == ResponseCode.ERROR.getCode()) {
            return responseFormat;
        }
        if (monthlyfeeDevice.getAdminUserId() == null) {
            Integer depId = this.adminUserService.getDepId(userId);
            monthlyfeeDevice.setDepId(depId);
            monthlyfeeDevice.setAdminUserId(userId);
        } else {
            if (!this.adminUserService.existsUser(monthlyfeeDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            monthlyfeeDevice.setDepId(this.adminUserService.getDepId(monthlyfeeDevice.getAdminUserId()));
        }
        monthlyfeeDevice.setStatus(MonthlyDeviceStatus.FREE.getStatus());
        this.monthlyfeeDeviceService.save(monthlyfeeDevice);
        return ResponseFormat.success();
    }

    /**
     * 修改氧气设备
     */
    @PutMapping("/oxygen-update")
    @ApiOperation("修改氧气设备")
    @ResourcesRoleMapping(resourceName = "修改氧气包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat updateOxygenDevice(@RequestBody @Validated(value = UpdateGroup.class) MonthlyOxygenDevice monthlyOxygenDevice) {
        QueryWrapper<MonthlyOxygenDevice> q1 = new QueryWrapper<>();
        q1.select("device_code", "admin_user_id");
        q1.eq("id", monthlyOxygenDevice.getId());
        MonthlyOxygenDevice oxygenDevice = this.oxygenDeviceService.getOne(q1);

        if (monthlyOxygenDevice.getAdminUserId() != null && !StringUtils.equals(String.valueOf(oxygenDevice.getAdminUserId()), String.valueOf(monthlyOxygenDevice.getAdminUserId()))) {
            if (!this.adminUserService.existsUser(monthlyOxygenDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            monthlyOxygenDevice.setAdminDepId(this.adminUserService.getDepId(monthlyOxygenDevice.getAdminUserId()));
        }

        if (!oxygenDevice.getDeviceCode().equals(monthlyOxygenDevice.getDeviceCode())) {
            //修改了机器码
            QueryWrapper<MonthlyOxygenDevice> q2 = new QueryWrapper<>();
            q2.eq("device_code", monthlyOxygenDevice.getDeviceCode());
            if (this.oxygenDeviceService.count(q2) >= 1) {
                return ResponseFormat.fail("机器码重复");
            }
        }
        this.oxygenDeviceService.updateById(monthlyOxygenDevice);
        return ResponseFormat.success();
    }

    /**
     * 修改臭氧设备
     */
    @PutMapping("/ozone-update")
    @ApiOperation("修改臭氧设备")
    @ResourcesRoleMapping(resourceName = "修改臭氧包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat updateOzoneDevice(@RequestBody @Validated(UpdateGroup.class) MonthlyfeeDevice monthlyfeeDevice) {
        QueryWrapper<MonthlyfeeDevice> q1 = new QueryWrapper<>();
        q1.select("device_code", "admin_user_id");
        q1.eq("id", monthlyfeeDevice.getId());
        MonthlyfeeDevice device = this.monthlyfeeDeviceService.getOne(q1);

        if (monthlyfeeDevice.getAdminUserId() != null && !StringUtils.equals(String.valueOf(device.getAdminUserId()), String.valueOf(monthlyfeeDevice.getAdminUserId()))) {
            if (!this.adminUserService.existsUser(monthlyfeeDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            monthlyfeeDevice.setDepId(this.adminUserService.getDepId(monthlyfeeDevice.getAdminUserId()));
        }

        if (!device.getDeviceCode().equals(monthlyfeeDevice.getDeviceCode())) {
            if (!this.monthlyfeeDeviceService.okCode(monthlyfeeDevice.getDeviceCode())) {
                return ResponseFormat.fail("机器码重复");
            }
        }
        this.monthlyfeeDeviceService.updateById(monthlyfeeDevice);
        return ResponseFormat.success();
    }

    /**
     * 删除氧气包月设备
     */
    @DeleteMapping("/oxygen-delete/{id}")
    @ApiOperation("删除氧气设备")
    @ResourcesRoleMapping(resourceName = "删除氧气包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat deleteOxygenDevice(@PathVariable("id") Integer oxygenDeviceId) {
        /**
         * 是否被绑定了?
         */
        QueryWrapper<MonthlyfeeDevice> q1 = new QueryWrapper<>();
        q1.eq("oxygen_id", oxygenDeviceId);
        if (this.monthlyfeeDeviceService.count(q1) > 0) {
            return ResponseFormat.fail("当前氧气机被臭氧机绑定着,不可删除");
        }
        QueryWrapper<MonthlyOxygenDevice> q2 = new QueryWrapper<>();
        q2.select("admin_user_id", "department_id");
        q2.eq("id", oxygenDeviceId);
        this.oxygenDeviceService.removeById(oxygenDeviceId);
        return ResponseFormat.success();
    }

    /**
     * 删除臭氧包月设备
     */
    @DeleteMapping("/ozone-delete/{id}")
    @ApiOperation("删除臭氧设备")
    @ResourcesRoleMapping(resourceName = "删除臭氧包月机器", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_MONTHLY})
    public ResponseFormat deleteDevice(@PathVariable("id") Integer deviceId) {
        //能否删除? 借出状态||非自己就不可删除
        QueryWrapper<MonthlyfeeDevice> q1 = new QueryWrapper<>();
        q1.select("admin_user_id", "status");
        q1.eq("id", deviceId);
        MonthlyfeeDevice monthlyfeeDevice = this.monthlyfeeDeviceService.getOne(q1);
        String status = monthlyfeeDevice.getStatus();
        if (status.equals(MonthlyDeviceStatus.INUSE.getStatus())) {
            return ResponseFormat.fail("借出中,不可删除");
        }
        this.monthlyfeeDeviceService.removeById(deviceId);
        return ResponseFormat.success();
    }

    /**
     * 绑定时检验当前氧气机id是否合格,是否被绑定
     */
    @GetMapping("/oxygen-valid")
    @ApiOperation("臭氧机器绑定时,对绑定的氧气机校验(传入氧气机id)")
    public ResponseFormat oxygenValid(@RequestParam("deviceId") Integer oxygenId) {
        return this.validOxygenCode(oxygenId);
    }

    /**
     * 为当前订单设置时间段
     */
    @PutMapping("/update-time-task")
    @ApiOperation("改变当前机器的时间段 (增加和修改一体,修改既是覆盖)  || 意思是: 和修改是一体的,再次添加时,会删除后再添加")
    public ResponseFormat updateTimeTask(@RequestBody AddTimeTaskBo timeTaskBo) {

        Integer deviceId = timeTaskBo.getDeviceId();
        Integer userId = MySecurity.getUserId();
        // 是否授权 是否为自己管理的机器
        QueryWrapper<MonthlyUserDevice> q1 = new QueryWrapper<>();
        q1.select("trusteeship");
        q1.eq("device_id", deviceId);
        MonthlyUserDevice userDevice = this.userDeviceService.getOne(q1);
        if (userDevice == null) {
            return ResponseFormat.fail("当前机器不存在1");
        }
        if (!userDevice.getTrusteeship()) {
            return ResponseFormat.fail("当前用户未开启托管");
        }

        QueryWrapper<MonthlyfeeDevice> q2 = new QueryWrapper<>();
        q2.select("admin_user_id");
        q2.eq("id", deviceId);
        MonthlyfeeDevice monthlyfeeDevice = this.monthlyfeeDeviceService.getOne(q2);
        if (monthlyfeeDevice == null) {
            return ResponseFormat.fail("当前机器不存在2");
        }
        if (!monthlyfeeDevice.getAdminUserId().equals(userId)) {
            return ResponseFormat.fail("不可操作其他业务员机器");
        }

        //默认删除
        QueryWrapper<MonthlyTimedTask> q3 = new QueryWrapper<>();
        q3.eq("device_id", deviceId);
        this.timedTaskService.remove(q3);
        //再添加
        MonthlyTimedTask monthlyTimedTask = new MonthlyTimedTask(deviceId);
        TimedTask timedTask = new TimedTask();
        for (AddTimeTaskBo.TimeSlot slot : timeTaskBo.getList()) {
            if (!timedTask.addTimeNode(slot.getStartDate(), slot.getEndDate())) {
                return ResponseFormat.fail("时间段不符合规则");
            }
        }
        monthlyTimedTask.setTimedTask(timedTask);
        this.timedTaskService.save(monthlyTimedTask);

        return ResponseFormat.success();
    }

    /**
     * 查询当前机器是否开启了定时任务 并且返回它的定时任务时间
     */
    @GetMapping("/time-task")
    @ApiOperation("查看当前机器是否开启了定时任务 + 并返回它的定时任务时间段")
    public ResponseFormat timeTask(@RequestParam("deviceId") Integer deviceId) {
        QueryWrapper<MonthlyTimedTask> q1 = new QueryWrapper<>();
        q1.select("open", "timed_task");
        q1.eq("device_id", deviceId);
        MonthlyTimedTask timedTask = this.timedTaskService.getOne(q1);
        return ResponseFormat.success(timedTask);
    }

    /**
     * 开启或者关闭时间段
     */
    @PutMapping("/changeTimeTask/{deviceId}")
    @ApiOperation("指定一台机器id,开启或者关闭它的定时任务 | 关闭则开启,开启则关闭")
    @ForbidMultipleClick(prefixKey = "changeTimeTask", key = "#deviceId")
    public ResponseFormat changeTimeTask(@PathVariable Integer deviceId) {

        Integer userId = MySecurity.getUserId();
        // 是否授权 是否为自己管理的机器
        QueryWrapper<MonthlyUserDevice> q1 = new QueryWrapper<>();
        q1.select("trusteeship", "user_id");
        q1.eq("device_id", deviceId);
        MonthlyUserDevice userDevice = this.userDeviceService.getOne(q1);
        if (userDevice == null) {
            return ResponseFormat.fail("当前机器不存在1");
        }
        if (!userDevice.getTrusteeship()) {
            return ResponseFormat.fail("当前用户未开启托管");
        }

        QueryWrapper<MonthlyfeeDevice> q2 = new QueryWrapper<>();
        q2.select("admin_user_id");
        q2.eq("id", deviceId);
        MonthlyfeeDevice monthlyfeeDevice = this.monthlyfeeDeviceService.getOne(q2);
        if (monthlyfeeDevice == null) {
            return ResponseFormat.fail("当前机器不存在2");
        }
        if (!monthlyfeeDevice.getAdminUserId().equals(userId)) {
            return ResponseFormat.fail("不可操作其他业务员机器");
        }

        QueryWrapper<MonthlyTimedTask> q3 = new QueryWrapper<>();
        q3.select("id");
        q3.eq("device_id", deviceId);
        MonthlyTimedTask timedTask = this.timedTaskService.getOne(q3);
        if (timedTask == null) {
            return ResponseFormat.fail("当前机器未设定时间任务");
        }

        // userId 和 定时任务id 然后请求一下local地址 直接请求即可,客户端会判断状态转弯
        this.stringRedisTemplate.opsForList().rightPush(TimedTask.redisKey, String.valueOf(userId));
        ResponseEntity<String> forEntity = this.restTemplate.getForEntity("http://127.0.0.1:" + this.clientPort + "/local/time-task", String.class);
        System.out.println("请求后的响应:" + forEntity);

        return ResponseFormat.success();
    }

    private ResponseFormat validDeviceSelectBo(SelectMonDeviceBo selectMonDeviceBo) {
        String role = MySecurity.getRole();
        Set<String> roles = MySecurity.getRoles();
        if (!roles.contains(MyRole.POWER_MONTHLY)) {
            if (role.equals(MyRole.DISTRIBUTOR)) {
                if (selectMonDeviceBo.getDepId() != null) {
                    //业务员不可访问部门机器
                    return ResponseFormat.fail("权限不足");
                }
                //只能访问属于自己的机器
                selectMonDeviceBo.setAdminUserId(MySecurity.getUserId());
            }
            if (role.equals(MyRole.AGENT)) {
                if (selectMonDeviceBo.getDepId() == null) {
                    return ResponseFormat.fail("只能查询自己的部门机器");
                }
                Integer userId = MySecurity.getUserId();
                QueryWrapper<AdminUser> q1 = new QueryWrapper<>();
                q1.select("department_id");
                q1.eq("id", userId);
                Integer departmentId = this.adminUserService.getOne(q1).getDepartmentId();
                if (!selectMonDeviceBo.getDepId().equals(departmentId)) {
                    return ResponseFormat.fail("只能查询自己的部门机器");
                }
            }
        }
        return ResponseFormat.success();
    }

    private ResponseFormat validOxygenCode(Integer oxygenId) {
        /**
         * 是否存在
         */
        QueryWrapper<MonthlyOxygenDevice> q1 = new QueryWrapper<>();
        q1.eq("id", oxygenId);
        if (this.oxygenDeviceService.count(q1) == 0) {
            return ResponseFormat.fail("对应氧气机不存在");
        }
        /**
         * 检测当前氧气机是否已经被绑定
         * 可以多绑定
         */
//        QueryWrapper<MonthlyfeeDevice> q2=new QueryWrapper<>();
//        q2.eq("oxygen_id",oxygenId);
//        if(monthlyfeeDeviceService.count(q2)>=1){
//            return ResponseFormat.fail("当前氧气机已被绑定");
//        }
        return ResponseFormat.success();
    }

}
